#ifndef CPARTICLE_H
#define CPARTICLE_H

#include <vector>
#include <iostream>
#include <stdio.h>
#include <string>
#include <math.h>
#include <time.h>
#include <list>
using namespace std;

#include "../Pattern/CPattern.h"
#include "../Point/CPoint.h"
int id_generator = 1;

class CParticleTraits {
public:
	typedef double						value_pattern_t;
	typedef CPattern<value_pattern_t>	pattern_t;
	typedef long double					gravity_t;
	typedef long double					velocity_t;
	typedef long double					angle_t;
	typedef string						label_t;
	typedef long double					position_t;
	typedef long double					aceleration_t;
};


template <typename _CT> class CParticle{
public:
	typedef typename _CT::value_pattern_t	value_pattern_t;
	typedef typename _CT::pattern_t			pattern_t;
	typedef typename _CT::gravity_t			gravity_t;
	typedef typename _CT::velocity_t		velocity_t;
	typedef typename _CT::angle_t			angle_t;
	typedef typename _CT::label_t			label_t;
	typedef typename _CT::position_t		position_t;
	typedef typename _CT::aceleration_t		aceleration_t;
	typedef list<pattern_t>					container_t;
	typedef CPoint<long double>					point_t;
	
public:
	container_t		_container;  //  implicit mass.
	point_t			_position;
	//point_t			_distance;
	long double		_distance;
	pattern_t		_mean;
	long double		_roche_limit;
	int				_id;

public:
	CParticle (pattern_t _p = pattern_t(), int _x = 0, int _y = 0)
		: _position(point_t(_x,_y)), _roche_limit (NULL){
		_container.push_back(_p);
		_mean = _p;
		_id = id_generator++;
		_distance = NULL;
	}

	point_t& operator * (){
		return _position;
	}

	pattern_t& mean (){
		return _mean;
	}

	bool operator() (CParticle& _np) {
		if (this->_id == _np._id) return false;
		container_t::iterator it = _np._container.begin();
		for (; it != _np._container.end(); it++)
			(*this)(*it);
		return true;
	}


	void operator() (const pattern_t& _np) {
		_mean *= _container.size();
		_container.push_back(_np);
		_mean += _np;
		_mean /= _container.size();
	}

	int size () {
		return _container.size();
	}

	template <typename __CT>
	friend ostream& operator << (ostream& out, CParticle<__CT>& _p){
//		out << "Id: " << _p._id  << endl;
//		out << "Media: " << _p._mean << endl;
//		out << "Masa: " << _p._container.size() << endl;
		out << "Posicion: " << _p._position ;//<< endl;
//		out << "Distance: " << _p._distance << endl;
//		out << "Roche: " << _p._roche_limit << endl;
		return out;
	}

};

#endif